package ru.spb.nicetu.altx.mnemo.node;

import java.io.Serializable;
import java.util.List;

import org.eclipse.core.runtime.IAdaptable;

import ru.spb.nicetu.altx.mnemo.cell.INodeCell;
import ru.spb.nicetu.altx.mnemo.extpoint.valuetypes.ITemplateValueType;
import ru.spb.nicetu.altx.mnemo.messages.IRunObservable;

/**
 * "NODE", или узел мнемосхемы
 */
public interface INode extends IRunObservable, Serializable, IAdaptable, IDable {
  /**
   * @return "Каноническое имя NODE-а", общее для какой-либо группы сходных
   *         NODE-ов
   */
  String getName();

  // void setName(String name);

  /**
   * @return "Собственное имя NODE-а"
   */
  String getConcreteName();

  void setConcreteName(String concreteName);

  /**
   * Добавление Ячейки в нужную группу. Группа зависит от категории Ячейки.
   * 
   * @param cell
   *          - добавляемая Ячейка
   */
  void addNodeCell(INodeCell cell);

  /**
   * Добавление Ячейки в группу входных ячеек NODE-а
   * 
   * @param cell
   *          - добавляемая Ячейка
   */
  // void addInputNodeCell(INodeCell cell);
  /**
   * Добавление Ячейки в группу выходных ячеек NODE-а
   * 
   * @param cell
   *          - добавляемая Ячейка
   */
  // void addOutputNodeCell(INodeCell cell);
  /**
   * Добавление Ячейки в группу настроечных параметров NODE-a
   * 
   * @param cell
   *          - добавляемая Ячейка
   */
  // void addSettingNodeCell(INodeCell cell);
  /**
   * Удаление Ячейки из группы входных ячеек NODE-а
   * 
   * @param cell
   *          - удаляемая Ячейка
   */
  void removeInputNodeCell(INodeCell cell);

  /**
   * Удаление Ячейки из группы выходных ячеек NODE-а
   * 
   * @param cell
   *          - удаляемая Ячейка
   */
  void removeOutputNodeCell(INodeCell cell);

  /**
   * Удаление Ячейки из группы настроечных параметров NODE-a
   * 
   * @param cell
   */
  void removeSettingNodeCell(INodeCell cell);

  /**
   * @return Список всех входных ячеек NODE-а
   */
  List<INodeCell> getAllInputCells();

  /**
   * @return Список всех выходных ячеек NODE-а
   */
  List<INodeCell> getAllOutputCells();

  /**
   * @return Список всех ячеек, которые являются настроечными параметрами NODE'a
   */
  List<INodeCell> getAllSettingCells();

  /**
   * @return Первая ВХодный ячейка (если она не null), или первая ВЫХодная
   *         ячейка (если она не null), или null.
   */
  INodeCell getFirstCell();

  /**
   * Связывание ячейки myCell NODE-а с ячейкой другого NODE-а, т.о. после этого
   * ячейка myCell будет иметь в качестве ИСТОЧНИКА ЗНАЧЕНИЯ другую ячейку.
   * 
   * @param myCell
   *          - ячейка NODE-а, для которой задается источник значений
   * @param link
   *          - ссылка на ячейку другого NODE-а, определяющая
   *          "адрес источника значения"
   */
  void linkMeToNode(INodeCell myCell, ICellLink link);

  /**
   * Возвращает ИСТОЧНИКА ЗНАЧЕНИЯ для ячейки myCell
   * 
   * @param myCell
   *          - ячейка NODE-а, для которой задается источник значений
   * @return ссылка на ячейку другого NODE-а, определяющая
   *         "адрес источника значения"
   */
  ICellLink getLink(INodeCell myCell);

  /**
   * Удаляет ссылки на источник данных для всех ячеек, для которых источником
   * являются ячейки, принадлежащие переданному node.
   * 
   * @param node
   *          - NODE, ячейки которого являются источниками данных для наших
   *          ячеек
   */
  void removeLinksToNode(INode node);

  /**
   * Удаляет ссылки на источник данных для всех ячеек, которые содержат ссылку
   * "link"
   * 
   * @param link
   *          - ссылка, котрую надо удалить из наших ячеек
   */
  // void removeLinks(ICellLink link);
  /**
   * Добавляет ссылку на потребителя данных из ячейки, на которую указыает link
   * 
   * @param node
   *          - узел-потребитель
   * @param cell
   *          - ячейка, принадлежащая узлу-потребителю
   * @param link
   *          - ссылка на ячейку-источник значений
   */
  void doLinkToDestinationCell(INode node, INodeCell cell, ICellLink link);

  /**
   * Удаляет ссылку на потребителя данных из ячейки, на которую указывает link
   * 
   * @param node
   *          - узел-потребитель
   * @param cell
   *          - ячейка, принадлежащая узлу-потребителю
   * @param link
   *          - ссылка на ячейку-источник значений
   */
  void doUnlinkToDestinationCell(INode node, INodeCell cell, ICellLink link);

  /**
   * @return состояние "GoodValueSourceCondition", т.е.
   *         "Для всех входных ячеек имеются источники значений"
   */
  boolean isGoodValueSourceCondition();

  /**
   * Рассчитывает состояние "GoodValueSourceCondition", т.е.
   * "Для всех входных ячеек имеются источники значений"
   */
  void calcGoodValueSourceCondition();

  /**
   * Возвращает флаг, показывающий, выполнен ли node
   * 
   * @return true - если node выполнился, иначе false
   */
  boolean wasRunned();

  /**
   * Устанавливает новое значение флага wasRunned
   * 
   * @param wasRunned
   *          - новое значение флага wasRunned
   */
  void setWasRunned(boolean wasRunned);

  /**
   * @return true - если node готов к выполнению, иначе false
   */
  boolean isReadyToRun();

  /**
   * @return true - если node был прерван во время выполнения
   */
  boolean isInterrupted();

  /**
   * Запускает нод на выполнение
   */
  void run();

  /**
   * @param cell
   *          - ячейка, значение которой необходмо вычислить
   * @return - значение, которое хранится в вычислителе в выходной ячейке,
   *         связанной с cell
   */
  @SuppressWarnings("unchecked")
  ITemplateValueType getCellValue(INodeCell cell);

  /**
   * Задает значение value ячейке вычислителя, которая связана с cell
   * 
   * @param cell
   *          - ячейка узла, связанная с ячейкой вычислителя, значение которой
   *          необходимо задать
   * @param value
   *          - значение, которое нужно установить
   */
  @SuppressWarnings("unchecked")
  void setCellValue(INodeCell cell, ITemplateValueType value);

  /**
   * @param link
   *          - ссылка на узел {@link IDataNode} и его ячейку, для которых
   *          необходио проверить наличие готовых исходных данных
   * @return true - если источник данных для узла node был выполнен, иначе false
   */
  boolean hasDataForNodeRun(ICellLink link);

} // interface INode
